package com.hmy.finance.service.core.dto;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hmy.finance.api.bo.core.request.SupplementaryPauseAmountCalculateRequest;
import com.hmy.finance.api.bo.core.request.vos.DeviceInfoVo;
import com.hmy.finance.api.bo.core.response.SupplementaryPauseAmountCalculateResponse;
import com.hmy.finance.dal.po.DeviceRentalRecordPo;
import com.hmy.finance.service.core.dto.vos.DevicePauseFeeInfo;
import lombok.Data;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 补充报停金额计算请求
 *
 * @author songkf
 * @date 2024/4/23
 */
@Data
public class SupplementaryPauseAmountCalculateDto implements java.io.Serializable {
    private static final long serialVersionUID = -8306107460488614060L;
    //========== Request Parameters ==========
    /**
     * 客户ID
     */
    private Long customerId;
    /**
     * 合同ID
     */
    private Long contractId;
    /**
     * 业务单据ID
     */
    private Long businessBillId;

    /**
     * 补录报停设备信息
     */
    private List<DeviceInfoVo> supplementaryDeviceInfoList;
//    /**
//     * 补录报停天数
//     */
//    private Double supplementaryPauseDays;

    //========== Logic Process Parameters ===========
    /**
     * 补录报停总费用
     */
    private BigDecimal supplementaryPauseTotalAmount;
    /**
     * 补录报停设备费用
     */
    private List<DevicePauseFeeInfo> devicePauseFeeInfoList;
    /**
     * 在租设备信息
     */
    private List<DeviceRentalRecordPo> deviceRentalRecordPoList;

    public static SupplementaryPauseAmountCalculateDto buildFromRequest(SupplementaryPauseAmountCalculateRequest request) {
        SupplementaryPauseAmountCalculateDto dto = new SupplementaryPauseAmountCalculateDto();
        dto.setCustomerId(request.getCustomerId());
        dto.setContractId(request.getContractId());
        dto.setBusinessBillId(request.getBusinessBillId());
        dto.setSupplementaryDeviceInfoList(request.getSupplementaryDeviceInfoList());
//        dto.setSupplementaryPauseDays(request.getSupplementaryPauseDays());
        return dto;
    }

    public Wrapper<DeviceRentalRecordPo> buildDeviceRentalRecordPoLambdaQueryWrapper() {
        return Wrappers.lambdaQuery(DeviceRentalRecordPo.class)
                .eq(DeviceRentalRecordPo::getCustomerId, customerId)
                .eq(DeviceRentalRecordPo::getContractId, contractId)
                .and(wra -> {
                    for (DeviceInfoVo supplementaryDeviceInfo : supplementaryDeviceInfoList) {
                        wra.or(wrb -> wrb.eq(DeviceRentalRecordPo::getDeviceId, supplementaryDeviceInfo.getDeviceId()).eq(DeviceRentalRecordPo::getEntryFormId, supplementaryDeviceInfo.getEntryFormId()));
                    }
                });
    }

    public void calculateSupplementaryPauseTotalAmount() {
        supplementaryPauseTotalAmount = BigDecimal.ZERO;
        devicePauseFeeInfoList = new ArrayList<>();
        supplementaryDeviceInfoList.forEach(deviceInfoVo -> {
            DevicePauseFeeInfo devicePauseFeeInfo = new DevicePauseFeeInfo();
            devicePauseFeeInfo.setEntryFormId(deviceInfoVo.getEntryFormId());
            devicePauseFeeInfo.setDeviceId(deviceInfoVo.getDeviceId());
            devicePauseFeeInfo.setPauseFee(BigDecimal.ZERO);
            if (deviceRentalRecordPoList == null || deviceRentalRecordPoList.isEmpty()) {
                devicePauseFeeInfo.setPauseFee(null);
                devicePauseFeeInfo.setChargeDays(null);
            } else {
                //从在租设备中获取对应的设备信息
                DeviceRentalRecordPo deviceRentalRecordPo = deviceRentalRecordPoList.stream().filter(po -> po.getDeviceId().equals(deviceInfoVo.getDeviceId()) && po.getEntryFormId().equals(deviceInfoVo.getEntryFormId())).findFirst().orElse(null);
                if (deviceRentalRecordPo == null) {
                    devicePauseFeeInfo.setPauseFee(null);
                    devicePauseFeeInfo.setChargeDays(null);
                } else {
                    //计算报停费用
                    //判断当前设备是否是月租单价
                    if (deviceRentalRecordPo.getUseMonthlyRentalPrice()) {
                        devicePauseFeeInfo.setPauseFee((deviceRentalRecordPo.getMonthlyRentalPrice().multiply(BigDecimal.valueOf(deviceInfoVo.getPauseDays()))).divide(BigDecimal.valueOf(30), 2, RoundingMode.HALF_UP));
                    } else {
                        //使用日租单价*（总租赁天数-本次报停天数）得到日租总额，判断是否大于月租单价，大于则使用月租单价，否则使用日租总额
                        BigDecimal dailyRentalTotalAmount = deviceRentalRecordPo.getDailyRentalPrice().multiply(BigDecimal.valueOf(deviceRentalRecordPo.getTotalRentalDays() - deviceInfoVo.getPauseDays()));
                        if (dailyRentalTotalAmount.compareTo(deviceRentalRecordPo.getMonthlyRentalPrice()) > 0) {
                            devicePauseFeeInfo.setPauseFee((deviceRentalRecordPo.getMonthlyRentalPrice().multiply(BigDecimal.valueOf(deviceInfoVo.getPauseDays()))).divide(BigDecimal.valueOf(30), 2, RoundingMode.HALF_UP));
                        } else {
                            devicePauseFeeInfo.setPauseFee(deviceRentalRecordPo.getDailyRentalPrice().multiply(BigDecimal.valueOf(deviceInfoVo.getPauseDays())));
                        }
                    }
                    devicePauseFeeInfo.setChargeDays(deviceRentalRecordPo.getTotalRentalDays());
                    supplementaryPauseTotalAmount = supplementaryPauseTotalAmount.add(devicePauseFeeInfo.getPauseFee());
                }
            }
            devicePauseFeeInfoList.add(devicePauseFeeInfo);
        });
    }

    public SupplementaryPauseAmountCalculateResponse getResponse() {
        SupplementaryPauseAmountCalculateResponse response = new SupplementaryPauseAmountCalculateResponse();
        response.setSupplementaryPauseTotalAmount(supplementaryPauseTotalAmount);
        response.setDevicePauseFeeInfoList(devicePauseFeeInfoList.stream().map(this::accept).collect(Collectors.toList()));
        return response;
    }

    private SupplementaryPauseAmountCalculateResponse.DevicePauseFeeInfo accept(DevicePauseFeeInfo devicePauseFeeInfo) {
        SupplementaryPauseAmountCalculateResponse.DevicePauseFeeInfo devicePauseFeeInfo1 = new SupplementaryPauseAmountCalculateResponse.DevicePauseFeeInfo();
        BeanUtils.copyProperties(devicePauseFeeInfo, devicePauseFeeInfo1);
        return devicePauseFeeInfo1;
    }
}
